Alright, so from all of this what do I know?

Speed Differences: Flow increases speed differences Ablation decreases speed differences Darkness increases speed differences Distance increases speed differences Angles around 90 degrees have a bigger difference in speed

Heading Differences: Fish are more aligned when they are around 90 degrees, slightly less in ablated fish

Synchronization: Darkness increases synchronization

NND: Darkness increases NND Flow decreases NND

Nearest Neighbor Bearing: In darkness fish are more in front or behind In flow fish are more in positioned alongside each other

Sets up the functions that will be used later

rad2deg <- function(rad) {(rad * 180) / (pi)}
deg2rad <- function(deg) {(deg * pi) / (180)}
round_any <- function(x, accuracy, f=round){f(x/ accuracy) * accuracy}
ang_mean <- function(x){rad2deg(atan(mean(sin(deg2rad(x)))/mean(cos(deg2rad(x)))))}

fold_angle_0_360_to_0_180 <- function(x){abs(abs(x-180)-180)}

fold_angle_neg_180_180_to_neg_90_90 <- function(x){ifelse(x > 90,90-abs(90-x),ifelse(x < -90, -90+abs(-90-x), x))}

min_n <- function(x,n){sort(x)[1:n]}
max_n <- function(x,n){sort(x,decreasing = TRUE)[1:n]}

Reads in the data and alters it as needed

comp_data <- read.csv("Fish_Comp_Values.csv")
comp_data <- na.omit(comp_data)

comp_data <- comp_data %>% mutate(Flow = ifelse(Flow == "0", "Flow 0", "Flow 2")) %>%
                           mutate(Ablation = ifelse(Ablation == "N", "No Ablation", "Ablated")) %>%
                           mutate(Darkness = ifelse(Darkness == "N", "Light", "Dark")) %>%
                           filter(Distance <= 4) %>%
                           filter(abs(Speed_Diff) <= 6) %>% 
                           mutate(Speed_Diff = abs(Speed_Diff)) %>%
                           mutate(fold_heading_diff = abs(fold_angle_neg_180_180_to_neg_90_90(Heading_Diff))) %>%
                           mutate(Is_Aligned = ifelse(Heading_Diff < 30, 1, 0)) %>%
                           mutate(Is_Reversed = ifelse(Heading_Diff > 150, 1, 0)) %>%
                           separate(Fish, c("Fish1", "Fish2"),sep="x") %>%
                           mutate(Flow = factor(Flow), Ablation = factor(Ablation), Darkness = factor(Darkness)) %>%
                           mutate(Flow = fct_relevel(Flow, c("Flow 0","Flow 2"))) %>%
                           mutate(Ablation = fct_relevel(Ablation, c("No Ablation","Ablated"))) %>%
                           mutate(Darkness = fct_relevel(Darkness, c("Light","Dark"))) %>%
                           mutate(rad_Angle = Angle) %>%
                           mutate(sin_Angle = sin(rad_Angle), cos_Angle = cos(rad_Angle)) %>%
                           mutate(Flow_Ablation_Darkness = factor(paste(Flow,Ablation,Darkness,sep=", ")))
                           
                           #mutate(Angle = fold_angle_0_360_to_0_180(Angle))

sum_comp_data <- comp_data %>% mutate(X_Distance = round_any(X_Distance,0.25), 
                                      Y_Distance = round_any(abs(Y_Distance),0.25)) %>%
                               group_by(Flow,Ablation,Darkness,X_Distance,Y_Distance) %>%
                               summarise(Speed_Diff = mean(Speed_Diff),
                                         Heading_Diff = ang_mean(Heading_Diff),
                                         Sync = mean(Sync),
                                         Fold_Heading_Diff = mean(fold_heading_diff),
                                         Is_Aligned = mean(Is_Aligned),
                                         Is_Reversed = mean(Is_Reversed))
`summarise()` has grouped output by 'Flow', 'Ablation', 'Darkness', 'X_Distance'. You can override using the `.groups` argument.
comp_data_switch_fish <- comp_data %>% mutate(Fish3 = Fish1) %>%
                                       mutate(Fish1 = Fish2) %>%
                                       mutate(Fish2 = Fish3) %>%
                                       select(-c(Fish3))

comp_data_NND <- bind_rows(comp_data, comp_data_switch_fish) %>% group_by(Year,Month,Day,Trial,Fish1,Tailbeat.Num) %>%
                                                                 filter(Distance == min(Distance)) %>%
                                                                 ungroup()

comp_data_near_3 <- bind_rows(comp_data, comp_data_switch_fish) %>% group_by(Year,Month,Day,Trial,Fish1,Tailbeat.Num) %>%
                                                                 slice_min(Distance, n = 3) %>%
                                                                 ungroup() %>%
                                                                 distinct(Distance, .keep_all= TRUE)

#Basic Stats

speed_anova <- aov(Speed_Diff ~ Flow + Ablation + Darkness + Flow:Ablation + Flow:Darkness, data = comp_data_near_3)

Anova(speed_anova)
Anova Table (Type II tests)

Response: Speed_Diff
               Sum Sq   Df F value    Pr(>F)    
Flow            18.03    1 67.1684 3.222e-16 ***
Ablation         1.56    1  5.8279  0.015814 *  
Darkness         0.95    1  3.5464  0.059739 .  
Flow:Ablation    0.01    1  0.0254  0.873339    
Flow:Darkness    3.53    1 13.1677  0.000288 ***
Residuals     1203.00 4482                      
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
heading_anova <- aov(fold_heading_diff ~ Flow + Ablation + Darkness + Flow:Ablation + Flow:Darkness, data = comp_data_near_3)

Anova(heading_anova)
Anova Table (Type II tests)

Response: fold_heading_diff
               Sum Sq   Df F value    Pr(>F)    
Flow            44371    1 67.3744 2.907e-16 ***
Ablation          277    1  0.4210   0.51645    
Darkness        10451    1 15.8685 6.898e-05 ***
Flow:Ablation    1978    1  3.0042   0.08312 .  
Flow:Darkness      36    1  0.0549   0.81476    
Residuals     2951752 4482                      
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
sync_anova <- aov(Sync ~ Flow + Ablation + Darkness + Flow:Ablation + Flow:Darkness, data = comp_data_near_3)

Anova(sync_anova)
Anova Table (Type II tests)

Response: Sync
               Sum Sq   Df F value   Pr(>F)   
Flow            0.000    1  0.0052 0.942353   
Ablation        0.004    1  0.0568 0.811706   
Darkness        0.463    1  7.4662 0.006312 **
Flow:Ablation   0.022    1  0.3618 0.547558   
Flow:Darkness   0.204    1  3.2819 0.070117 . 
Residuals     277.923 4482                    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
dist_anova <- aov(Distance ~ Flow + Ablation + Darkness + Flow:Ablation + Flow:Darkness, data = comp_data_NND)

Anova(dist_anova)
Anova Table (Type II tests)

Response: Distance
               Sum Sq   Df  F value    Pr(>F)    
Flow             4.35    1   9.5503  0.002019 ** 
Ablation         0.15    1   0.3347  0.562954    
Darkness       102.00    1 223.9367 < 2.2e-16 ***
Flow:Ablation    0.01    1   0.0166  0.897363    
Flow:Darkness    1.86    1   4.0795  0.043503 *  
Residuals     1254.36 2754                       
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
angle_anova <- aov(Angle ~ Flow + Ablation + Darkness + Flow:Ablation + Flow:Darkness, data = comp_data_NND)

Anova(dist_anova)
Anova Table (Type II tests)

Response: Distance
               Sum Sq   Df  F value    Pr(>F)    
Flow             4.35    1   9.5503  0.002019 ** 
Ablation         0.15    1   0.3347  0.562954    
Darkness       102.00    1 223.9367 < 2.2e-16 ***
Flow:Ablation    0.01    1   0.0166  0.897363    
Flow:Darkness    1.86    1   4.0795  0.043503 *  
Residuals     1254.36 2754                       
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
ggplot(comp_data_near_3, aes(x = cos(deg2rad(Angle))))+
  geom_histogram()+
  facet_wrap(~ Flow + Ablation + Darkness)


ggplot(comp_data_near_3, aes(x = sin(deg2rad(Angle))))+
  geom_histogram()+
  facet_wrap(~ Flow + Ablation + Darkness)

ggplot(comp_data_near_3, aes(x = Flow, y = Speed_Diff, fill = interaction(Ablation,Darkness,sep=", ")))+
  geom_boxplot(outlier.shape = NA) +
  guides(fill = guide_legend(title = "Condition")) +
  scale_fill_manual(values=c("#EEEEEE", "#4CB944", "#00A7E1")) +
  ggtitle("Effect of Available Senses on Speed Difference") +
  xlab("") +
  ylab("Speed Difference (BL/s)") +
  ylim(-0.1,2.5) +
  theme_light()


ggplot(comp_data_near_3, aes(x = Flow, y = fold_heading_diff, fill = interaction(Ablation,Darkness,sep=", ")))+
  geom_boxplot(outlier.shape = NA) +
  guides(fill = guide_legend(title = "Condition")) +
  scale_fill_manual(values=c("#EEEEEE", "#4CB944", "#00A7E1")) +
  ggtitle("Effect of Available Senses on Heading Difference") +
  xlab("") +
  ylab("Heading Difference (Degrees)") +
  theme_light()


ggplot(comp_data_near_3, aes(x = Flow, y = Sync, fill = interaction(Ablation,Darkness,sep=", ")))+
  geom_boxplot(outlier.shape = NA) +
  guides(fill = guide_legend(title = "Condition")) +
  scale_fill_manual(values=c("#EEEEEE", "#4CB944", "#00A7E1")) +
  ggtitle("Effect of Available Senses on Tailbeat Synchonization") +
  xlab("") +
  ylab("Syncronization") +
  theme_light()


ggplot(comp_data_near_3, aes(x = Flow, y = Distance, fill = interaction(Ablation,Darkness,sep=", ")))+
  geom_boxplot(outlier.shape = NA) +
  guides(fill = guide_legend(title = "Condition")) +
  scale_fill_manual(values=c("#EEEEEE", "#4CB944", "#00A7E1")) +
  ggtitle("Effect of Available Senses on Nearest Neighbor Distance (NND)") +
  xlab("") +
  ylab("NND (BL)") +
  theme_light()


ggplot(comp_data_near_3, aes(x = Flow, y = Angle, fill = interaction(Ablation,Darkness,sep=", ")))+
  geom_boxplot(outlier.shape = NA) +
  guides(fill = guide_legend(title = "Condition")) +
  scale_fill_manual(values=c("#EEEEEE", "#4CB944", "#00A7E1")) +
  ggtitle("Effect of Available Senses on Nearest Neighbor Bearing") +
  xlab("") +
  ylab("Nearest Neighbor Bearing (Degrees)") +
  scale_y_continuous(breaks = c(30,60,90,120,150)) +
  theme_light()

Trying GAMs

speed_gam <- gam(Speed_Diff ~ s(Distance,Angle,by=Flow_Ablation_Darkness),
                              data = comp_data_near_3)

summary(speed_gam)

Family: gaussian 
Link function: identity 

Formula:
Speed_Diff ~ s(Distance, Angle, by = Flow_Ablation_Darkness)

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 0.621779   0.008037   77.37   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
                                                                     edf Ref.df      F  p-value    
s(Distance,Angle):Flow_Ablation_DarknessFlow 0, Ablated, Light     2.000  2.000 44.263  < 2e-16 ***
s(Distance,Angle):Flow_Ablation_DarknessFlow 0, No Ablation, Dark  2.000  2.000  3.355 0.034997 *  
s(Distance,Angle):Flow_Ablation_DarknessFlow 0, No Ablation, Light 4.572  5.822  4.413 0.000244 ***
s(Distance,Angle):Flow_Ablation_DarknessFlow 2, Ablated, Light     4.325  5.485  4.788 0.000154 ***
s(Distance,Angle):Flow_Ablation_DarknessFlow 2, No Ablation, Dark  4.133  5.230  5.702  2.5e-05 ***
s(Distance,Angle):Flow_Ablation_DarknessFlow 2, No Ablation, Light 2.000  2.000  8.196 0.000280 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =  0.0396   Deviance explained = 4.37%
GCV = 0.26585  Scale est. = 0.26466   n = 4488
heading_gam <- gam(fold_heading_diff ~ s(Distance,Angle,by=Flow_Ablation_Darkness),
                              data = comp_data_near_3)

summary(heading_gam)

Family: gaussian 
Link function: identity 

Formula:
fold_heading_diff ~ s(Distance, Angle, by = Flow_Ablation_Darkness)

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  38.6811     0.4036   95.83   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
                                                                     edf Ref.df     F p-value   
s(Distance,Angle):Flow_Ablation_DarknessFlow 0, Ablated, Light     7.027  9.057 2.905 0.00194 **
s(Distance,Angle):Flow_Ablation_DarknessFlow 0, No Ablation, Dark  2.000  2.000 0.626 0.53461   
s(Distance,Angle):Flow_Ablation_DarknessFlow 0, No Ablation, Light 2.000  2.000 1.010 0.36439   
s(Distance,Angle):Flow_Ablation_DarknessFlow 2, Ablated, Light     5.536  7.091 0.940 0.47446   
s(Distance,Angle):Flow_Ablation_DarknessFlow 2, No Ablation, Dark  6.922  8.829 3.047 0.00143 **
s(Distance,Angle):Flow_Ablation_DarknessFlow 2, No Ablation, Light 2.000  2.000 0.340 0.71198   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =  0.0113   Deviance explained = 1.69%
GCV = 670.78  Scale est. = 666.82    n = 4488
sync_gam <- gam(Sync ~ s(Distance,Angle,by=Flow_Ablation_Darkness),
                              data = comp_data_near_3)

summary(sync_gam)

Family: gaussian 
Link function: identity 

Formula:
Sync ~ s(Distance, Angle, by = Flow_Ablation_Darkness)

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 0.540504   0.003869   139.7   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
                                                                     edf Ref.df     F  p-value    
s(Distance,Angle):Flow_Ablation_DarknessFlow 0, Ablated, Light     5.433  6.967 4.868 1.89e-05 ***
s(Distance,Angle):Flow_Ablation_DarknessFlow 0, No Ablation, Dark  4.258  5.392 1.515   0.1816    
s(Distance,Angle):Flow_Ablation_DarknessFlow 0, No Ablation, Light 3.972  5.020 2.353   0.0381 *  
s(Distance,Angle):Flow_Ablation_DarknessFlow 2, Ablated, Light     4.563  5.803 1.955   0.0675 .  
s(Distance,Angle):Flow_Ablation_DarknessFlow 2, No Ablation, Dark  2.000  2.000 0.914   0.4010    
s(Distance,Angle):Flow_Ablation_DarknessFlow 2, No Ablation, Light 2.000  2.000 1.228   0.2929    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =  0.0132   Deviance explained = 1.81%
GCV = 0.061633  Scale est. = 0.061314  n = 4488

Now we make some predictions for this.

d <- seq(from = 0, to = 3, by = 0.1)
a <- seq(from = 0, to = 180, by = 10)

flows <- c("Flow 0", "Flow 2")
ablation <- c("No Ablation", "Ablated")
dark <- c("Light","Dark")

predict_df <- expand.grid(Distance = d, Angle = a, Flow = flows, Ablation = ablation, Darkness = dark)

predict_df <- predict_df %>% mutate(Flow_Ablation_Darkness = factor(paste(Flow,Ablation,Darkness,sep=", "))) %>% 
                            filter(!(Ablation == "Ablated" & Darkness == 'Dark'))

predict_df <- predict_df %>% mutate(pred_speed_diff = predict.gam(speed_gam,predict_df),
                                    pred_heading_diff = predict.gam(heading_gam,predict_df),
                                    pred_sync = predict.gam(sync_gam,predict_df))

predict_df <- predict_df %>% group_by(Distance,Flow,Ablation,Darkness) %>%
                             mutate(mean_Speed_Distance = mean(pred_speed_diff), sd_Speed_Distance = sd(pred_speed_diff),
                                    mean_Heading_Distance = mean(pred_heading_diff), sd_Heading_Distance = sd(pred_heading_diff),
                                    mean_Sync_Distance = mean(pred_sync), sd_Sync_Distance = sd(pred_sync)) %>%
                             ungroup() %>%
                             group_by(Angle,Flow,Ablation,Darkness) %>%
                             mutate(mean_Speed_Angle = mean(pred_speed_diff), sd_Speed_Angle = sd(pred_speed_diff),
                                    mean_Heading_Angle = mean(pred_heading_diff), sd_Heading_Angle = sd(pred_heading_diff),
                                    mean_Sync_Angle = mean(pred_sync), sd_Sync_Angle = sd(pred_sync)) %>%
                             ungroup()

And now we graph those?

ggplot(predict_df, aes(x = Distance, y = mean_Speed_Distance, color = interaction(Ablation,Darkness,sep=", "),
                       fill = interaction(Ablation,Darkness,sep=" "))) +
  geom_line() +
  #geom_point(data=predict_df, aes(x = Distance, y = pred_speed_diff, alpha = 0.15)) +
  geom_ribbon(aes(ymin = mean_Speed_Distance-sd_Speed_Distance, ymax = mean_Speed_Distance+sd_Speed_Distance),
              linetype = 0,
              alpha = 0.1) +
  facet_wrap(~ Flow) +
  guides(fill = "none", color = guide_legend(title = "Condition")) +
  scale_color_manual(values=c("#000000", "#4CB944", "#00A7E1")) +
  scale_fill_manual(values=c("#000000", "#4CB944", "#00A7E1")) +
  ggtitle("Effect of Distance and Senses on Speed Difference") +
  xlab("Distance (BL)") +
  ylab("Speed Difference (BL/s)") +
  ylim(0,1.5) +
  theme_light()


ggplot(predict_df, aes(x = Distance, y = mean_Heading_Distance, color = interaction(Ablation,Darkness,sep=", "),
                       fill = interaction(Ablation,Darkness,sep=", "))) +
  geom_line() +
  #geom_point(data=predict_df, aes(x = Distance, y = pred_heading_diff, alpha = 0.15)) +
  geom_ribbon(aes(ymin = mean_Heading_Distance-sd_Heading_Distance, ymax = mean_Heading_Distance+sd_Heading_Distance),
              linetype = 0,
              alpha = 0.1) +
  facet_wrap(~ Flow) +
  guides(fill = "none", color = guide_legend(title = "Condition")) +
  scale_color_manual(values=c("#000000", "#4CB944", "#00A7E1")) +
  scale_fill_manual(values=c("#000000", "#4CB944", "#00A7E1")) +
  ggtitle("Effect of Distance and Senses on Heading Difference") +
  xlab("Distance (BL)") +
  ylab("Heading Difference (Degrees)") +
  ylim(0,50) +
  theme_light()


ggplot(predict_df, aes(x = Distance, y = mean_Sync_Distance, color = interaction(Ablation,Darkness,sep=", "),
                       fill = interaction(Ablation,Darkness,sep=", "))) +
  geom_line() +
  #geom_point(data=predict_df, aes(x = Distance, y = pred_sync, alpha = 0.15)) +
  geom_ribbon(aes(ymin = mean_Sync_Distance-sd_Sync_Distance, ymax = mean_Sync_Distance+sd_Sync_Distance),
              linetype = 0,
              alpha = 0.1) +
  facet_wrap(~ Flow) +
  guides(fill = "none", color = guide_legend(title = "Condition")) +
  scale_color_manual(values=c("#000000", "#4CB944", "#00A7E1")) +
  scale_fill_manual(values=c("#000000", "#4CB944", "#00A7E1")) +
  ggtitle("Effect of Distance and Senses on Synchonization") +
  xlab("Distance (BL)") +
  ylab("Synchonization") +
  ylim(0,1)+
  theme_light()

ggplot(predict_df, aes(x = Angle, y = mean_Speed_Angle, color = interaction(Ablation,Darkness,sep=", "),
                       fill = interaction(Ablation,Darkness,sep=", "))) +
  geom_line() +
  geom_point(data=predict_df, aes(x = Angle, y = pred_speed_diff, alpha = 0.15)) +
  geom_ribbon(aes(ymin = mean_Speed_Angle-sd_Speed_Angle, ymax = mean_Speed_Angle+sd_Speed_Angle),
              linetype = 0,
              alpha = 0.1) +
  facet_wrap(~ Flow) +
  guides(fill = "none", color = guide_legend(title = "Condition")) +
  scale_color_manual(values=c("#000000", "#4CB944", "#00A7E1")) +
  scale_fill_manual(values=c("#000000", "#4CB944", "#00A7E1")) +
  ggtitle("Effect of Bearing and Senses on Speed Difference") +
  xlab("Bearing (Degrees)") +
  ylab("Speed Difference (BL/s)") +
  ylim(0,1.5) +
  theme_light()


ggplot(predict_df, aes(x = Angle, y = mean_Heading_Angle, color = interaction(Ablation,Darkness,sep=", "),
                       fill = interaction(Ablation,Darkness,sep=", "))) +
  geom_line() +
  geom_point(data=predict_df, aes(x = Angle, y = pred_heading_diff, alpha = 0.15)) +
  geom_ribbon(aes(ymin = mean_Heading_Angle-sd_Heading_Angle, ymax = mean_Heading_Angle+sd_Heading_Angle),
              linetype = 0,
              alpha = 0.1) +
  facet_wrap(~ Flow) +
  guides(fill = "none", color = guide_legend(title = "Condition")) +
  scale_color_manual(values=c("#000000", "#4CB944", "#00A7E1")) +
  scale_fill_manual(values=c("#000000", "#4CB944", "#00A7E1")) +
  ggtitle("Effect of Bearing and Senses on Heading Difference") +
  xlab("Angle (Degrees)") +
  ylab("Heading Difference (Degrees)") +
  ylim(0,50) +
  theme_light()


ggplot(predict_df, aes(x = Angle, y = mean_Sync_Angle, color = interaction(Ablation,Darkness,sep=", "),
                       fill = interaction(Ablation,Darkness,sep=", "))) +
  geom_line() +
  geom_point(data=predict_df, aes(x = Angle, y = pred_sync, alpha = 0.15)) +
  geom_ribbon(aes(ymin = mean_Sync_Angle-sd_Sync_Angle, ymax = mean_Sync_Angle+sd_Sync_Angle),
              linetype = 0,
              alpha = 0.1) +
  facet_wrap(~ Flow) +
  guides(fill = "none", color = guide_legend(title = "Condition")) +
  scale_color_manual(values=c("#000000", "#4CB944", "#00A7E1")) +
  scale_fill_manual(values=c("#000000", "#4CB944", "#00A7E1")) +
  ggtitle("Effect of Bearing and Senses on Synchonization") +
  xlab("Bearing (Degrees)") +
  ylab("Synchonization") +
  ylim(0,1)+
  theme_light()

Density vs Things

dist_bin_size <- 1
angle_bin_size <- 30

comp_data_freqs <- comp_data_near_3 %>% mutate(Dist_bin = round_any(Distance, dist_bin_size), 
                                               Angle_bin = round_any(Angle, angle_bin_size)) %>%
                                        group_by(Flow,Darkness,Ablation, Dist_bin, Angle_bin,Flow_Ablation_Darkness) %>%
                                        mutate(Count = n()) %>%
                                        ungroup() %>%
                                        group_by(Flow,Darkness,Ablation,Flow_Ablation_Darkness) %>%
                                        mutate(Freq = Count/n()) %>%
                                        ungroup() %>%
                                        group_by(Flow,Darkness,Ablation,Dist_bin,Angle_bin,Flow_Ablation_Darkness) %>%
                                        summarise(Speed_Diff = mean(Speed_Diff),
                                                  Fold_Heading_Diff = ang_mean(fold_heading_diff),
                                                  Sync = mean(Sync),
                                                  Freq = mean(Freq))
`summarise()` has grouped output by 'Flow', 'Darkness', 'Ablation', 'Dist_bin', 'Angle_bin'. You can override using the `.groups` argument.
freq_speed_glm <- glm(Speed_Diff ~ Freq*(Flow+Darkness+Ablation+Flow:Ablation+Flow:Darkness), data = comp_data_freqs)

summary(freq_speed_glm)

Call:
glm(formula = Speed_Diff ~ Freq * (Flow + Darkness + Ablation + 
    Flow:Ablation + Flow:Darkness), data = comp_data_freqs)

Deviance Residuals: 
     Min        1Q    Median        3Q       Max  
-0.58056  -0.14862  -0.03226   0.10369   1.67245  

Coefficients:
                                Estimate Std. Error t value Pr(>|t|)    
(Intercept)                       0.7069     0.0724   9.764   <2e-16 ***
Freq                             -2.2974     1.7766  -1.293   0.1977    
FlowFlow 2                        0.1974     0.1070   1.846   0.0667 .  
DarknessDark                     -0.2170     0.1176  -1.845   0.0668 .  
AblationAblated                   0.1003     0.1035   0.968   0.3342    
FlowFlow 2:AblationAblated       -0.3068     0.1521  -2.017   0.0453 *  
FlowFlow 2:DarknessDark           0.3467     0.1707   2.031   0.0438 *  
Freq:FlowFlow 2                  -1.3837     2.4277  -0.570   0.5694    
Freq:DarknessDark                 3.5412     2.9607   1.196   0.2333    
Freq:AblationAblated             -2.2364     2.4558  -0.911   0.3638    
Freq:FlowFlow 2:AblationAblated   4.7660     3.3948   1.404   0.1621    
Freq:FlowFlow 2:DarknessDark     -4.6976     4.0855  -1.150   0.2518    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for gaussian family taken to be 0.08537927)

    Null deviance: 18.369  on 183  degrees of freedom
Residual deviance: 14.685  on 172  degrees of freedom
AIC: 83

Number of Fisher Scoring iterations: 2
freq_heading_glm <- glm(Fold_Heading_Diff ~ Freq*(Flow+Darkness+Ablation+Flow:Ablation+Flow:Darkness), data = comp_data_freqs)

summary(freq_heading_glm)

Call:
glm(formula = Fold_Heading_Diff ~ Freq * (Flow + Darkness + Ablation + 
    Flow:Ablation + Flow:Darkness), data = comp_data_freqs)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-35.899   -4.374   -0.533    4.584   41.173  

Coefficients:
                                Estimate Std. Error t value Pr(>|t|)    
(Intercept)                       29.280      2.293  12.772  < 2e-16 ***
Freq                             105.736     56.256   1.880  0.06186 .  
FlowFlow 2                        16.080      3.387   4.748 4.31e-06 ***
DarknessDark                       7.954      3.724   2.136  0.03411 *  
AblationAblated                    8.450      3.278   2.578  0.01078 *  
FlowFlow 2:AblationAblated       -13.779      4.817  -2.861  0.00475 ** 
FlowFlow 2:DarknessDark          -16.857      5.406  -3.118  0.00213 ** 
Freq:FlowFlow 2                 -179.547     76.873  -2.336  0.02066 *  
Freq:DarknessDark                -60.112     93.753  -0.641  0.52227    
Freq:AblationAblated            -172.808     77.766  -2.222  0.02758 *  
Freq:FlowFlow 2:AblationAblated  279.733    107.498   2.602  0.01007 *  
Freq:FlowFlow 2:DarknessDark     304.057    129.368   2.350  0.01989 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for gaussian family taken to be 85.60996)

    Null deviance: 18576  on 183  degrees of freedom
Residual deviance: 14725  on 172  degrees of freedom
AIC: 1354.5

Number of Fisher Scoring iterations: 2
freq_sync_glm <- glm(Sync ~ Freq*(Flow+Darkness+Ablation+Flow:Ablation+Flow:Darkness), data = comp_data_freqs)

summary(freq_sync_glm)

Call:
glm(formula = Sync ~ Freq * (Flow + Darkness + Ablation + Flow:Ablation + 
    Flow:Darkness), data = comp_data_freqs)

Deviance Residuals: 
     Min        1Q    Median        3Q       Max  
-0.49785  -0.05122  -0.00219   0.05194   0.36839  

Coefficients:
                                  Estimate Std. Error t value Pr(>|t|)    
(Intercept)                      0.5736663  0.0301319  19.039   <2e-16 ***
Freq                            -0.7636827  0.7394078  -1.033    0.303    
FlowFlow 2                       0.0008242  0.0445166   0.019    0.985    
DarknessDark                     0.1008135  0.0489509   2.059    0.041 *  
AblationAblated                 -0.0172332  0.0430865  -0.400    0.690    
FlowFlow 2:AblationAblated       0.0064293  0.0633081   0.102    0.919    
FlowFlow 2:DarknessDark         -0.1166197  0.0710527  -1.641    0.103    
Freq:FlowFlow 2                  0.3182002  1.0103926   0.315    0.753    
Freq:DarknessDark               -1.3454754  1.2322589  -1.092    0.276    
Freq:AblationAblated             0.3667070  1.0221233   0.359    0.720    
Freq:FlowFlow 2:AblationAblated -0.3483264  1.4129158  -0.247    0.806    
Freq:FlowFlow 2:DarknessDark     1.6647306  1.7003671   0.979    0.329    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for gaussian family taken to be 0.01478952)

    Null deviance: 2.7261  on 183  degrees of freedom
Residual deviance: 2.5438  on 172  degrees of freedom
AIC: -239.59

Number of Fisher Scoring iterations: 2
freq_speed_gam <- gam(Speed_Diff ~ s(Freq,by=Flow_Ablation_Darkness),
                              data = comp_data_freqs)

summary(freq_speed_gam)

Family: gaussian 
Link function: identity 

Formula:
Speed_Diff ~ s(Freq, by = Flow_Ablation_Darkness)

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  0.65610    0.02396   27.39   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
                                                           edf Ref.df     F p-value  
s(Freq):Flow_Ablation_DarknessFlow 0, Ablated, Light     1.369  1.645 3.648  0.0241 *
s(Freq):Flow_Ablation_DarknessFlow 0, No Ablation, Dark  1.243  1.446 0.430  0.7141  
s(Freq):Flow_Ablation_DarknessFlow 0, No Ablation, Light 1.000  1.000 1.489  0.2240  
s(Freq):Flow_Ablation_DarknessFlow 2, Ablated, Light     1.000  1.000 0.457  0.4998  
s(Freq):Flow_Ablation_DarknessFlow 2, No Ablation, Dark  8.018  8.330 2.528  0.0135 *
s(Freq):Flow_Ablation_DarknessFlow 2, No Ablation, Light 1.321  1.571 2.232  0.0801 .
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =  0.114   Deviance explained = 18.2%
GCV = 0.096783  Scale est. = 0.08892   n = 184
freq_heading_gam <- gam(Fold_Heading_Diff ~ s(Freq,by=Flow_Ablation_Darkness),
                              data = comp_data_freqs)

summary(freq_heading_gam)

Family: gaussian 
Link function: identity 

Formula:
Fold_Heading_Diff ~ s(Freq, by = Flow_Ablation_Darkness)

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  39.7569     0.7495   53.05   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
                                                           edf Ref.df     F p-value    
s(Freq):Flow_Ablation_DarknessFlow 0, Ablated, Light     1.000  1.000 1.278 0.25978    
s(Freq):Flow_Ablation_DarknessFlow 0, No Ablation, Dark  1.000  1.000 0.379 0.53893    
s(Freq):Flow_Ablation_DarknessFlow 0, No Ablation, Light 7.190  7.969 3.942 0.00028 ***
s(Freq):Flow_Ablation_DarknessFlow 2, Ablated, Light     1.391  1.677 0.300 0.59859    
s(Freq):Flow_Ablation_DarknessFlow 2, No Ablation, Dark  1.000  1.000 6.038 0.01501 *  
s(Freq):Flow_Ablation_DarknessFlow 2, No Ablation, Light 1.000  1.000 1.688 0.19564    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =   0.15   Deviance explained = 20.8%
GCV = 93.207  Scale est. = 86.328    n = 184
freq_sync_gam <- gam(Sync ~ s(Freq,by=Flow_Ablation_Darkness),
                              data = comp_data_freqs)

summary(freq_sync_gam)

Family: gaussian 
Link function: identity 

Formula:
Sync ~ s(Freq, by = Flow_Ablation_Darkness)

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 0.552151   0.009333   59.16   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
                                                           edf Ref.df     F p-value   
s(Freq):Flow_Ablation_DarknessFlow 0, Ablated, Light     1.000  1.000 0.328 0.56755   
s(Freq):Flow_Ablation_DarknessFlow 0, No Ablation, Dark  5.900  6.791 3.273 0.00286 **
s(Freq):Flow_Ablation_DarknessFlow 0, No Ablation, Light 2.973  3.709 1.168 0.26685   
s(Freq):Flow_Ablation_DarknessFlow 2, Ablated, Light     1.000  1.000 0.431 0.51217   
s(Freq):Flow_Ablation_DarknessFlow 2, No Ablation, Dark  1.000  1.000 0.017 0.89556   
s(Freq):Flow_Ablation_DarknessFlow 2, No Ablation, Light 1.000  1.000 0.436 0.51011   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =  0.101   Deviance explained = 16.4%
GCV = 0.014483  Scale est. = 0.013391  n = 184

Now we make some predictions for this.

f <- seq(from = 0.005, to = 0.07, by = 0.001)

flows <- c("Flow 0", "Flow 2")
ablation <- c("No Ablation", "Ablated")
dark <- c("Light","Dark")

freq_predict_df <- expand.grid(Freq = f, Flow = flows, Ablation = ablation, Darkness = dark)

freq_predict_df <- freq_predict_df %>% mutate(Flow_Ablation_Darkness = factor(paste(Flow,Ablation,Darkness,sep=", "))) %>% 
                            filter(!(Ablation == "Ablated" & Darkness == 'Dark'))

freq_predict_df <- freq_predict_df %>% mutate(pred_speed_diff = predict.gam(freq_speed_gam,freq_predict_df),
                                    pred_heading_diff = predict.gam(freq_heading_gam,freq_predict_df),
                                    pred_sync = predict.gam(freq_sync_gam,freq_predict_df))
ggplot(comp_data_freqs, aes(x = Freq, y = Speed_Diff, color = interaction(Ablation,Darkness,sep=", "),
                       fill = interaction(Ablation,Darkness,sep=", "))) +
  geom_point(alpha = 0.5) +
  geom_smooth(method = "lm", formula = "y ~ x", se = FALSE) +
  facet_wrap(~ Flow) +
  guides(fill = "none", color = guide_legend(title = "Condition")) +
  scale_color_manual(values=c("#000000", "#4CB944", "#00A7E1")) +
  scale_fill_manual(values=c("#000000", "#4CB944", "#00A7E1")) +
  ggtitle("Effect of Preference and Senses on Speed Difference") +
  xlab("Frequency of Observations") +
  ylab("Speed Difference (BL/s)") +
  theme_light()


ggplot(comp_data_freqs, aes(x = Freq, y = Fold_Heading_Diff, color = interaction(Ablation,Darkness,sep=", "),
                       fill = interaction(Ablation,Darkness,sep=", "))) +
  geom_point(alpha = 0.5) +
  geom_smooth(method = "lm", formula = "y ~ x", se = FALSE) +
  facet_wrap(~ Flow) +
  guides(fill = "none", color = guide_legend(title = "Condition")) +
  scale_color_manual(values=c("#000000", "#4CB944", "#00A7E1")) +
  scale_fill_manual(values=c("#000000", "#4CB944", "#00A7E1")) +
  ggtitle("Effect of Preference and Senses on Heading Difference") +
  xlab("Frequency of Observations") +
  ylab("Heading Difference (Degrees)") +
  theme_light()


ggplot(comp_data_freqs, aes(x = Freq, y = Sync, color = interaction(Ablation,Darkness,sep=", "),
                       fill = interaction(Ablation,Darkness,sep=", "))) +
  geom_point(alpha = 0.5) +
  geom_smooth(method = "lm", formula = "y ~ x", se = FALSE) +
  facet_wrap(~ Flow) +
  guides(fill = "none", color = guide_legend(title = "Condition")) +
  scale_color_manual(values=c("#000000", "#4CB944", "#00A7E1")) +
  scale_fill_manual(values=c("#000000", "#4CB944", "#00A7E1")) +
  ggtitle("Effect of Preference and Senses on Synchonization") +
  xlab("Frequency of Observations") +
  ylab("Synchonization") +
  theme_light()

ggplot(freq_predict_df, aes(x = Freq, y = pred_speed_diff, color = interaction(Ablation,Darkness,sep=", "),
                       fill = interaction(Ablation,Darkness,sep=", "))) +
  geom_line() +
  facet_wrap(~ Flow) +
  guides(fill = "none", color = guide_legend(title = "Condition")) +
  scale_color_manual(values=c("#000000", "#4CB944", "#00A7E1")) +
  scale_fill_manual(values=c("#000000", "#4CB944", "#00A7E1")) +
  ggtitle("Effect of Frequency of Observations on Speed Difference") +
  xlab("Frequency (%)") +
  ylab("Speed Difference (BL/s)") +
  theme_light()


ggplot(freq_predict_df, aes(x = Freq, y = pred_heading_diff, color = interaction(Ablation,Darkness,sep=", "),
                       fill = interaction(Ablation,Darkness,sep=", "))) +
  geom_line() +
  facet_wrap(~ Flow) +
  guides(fill = "none", color = guide_legend(title = "Condition")) +
  scale_color_manual(values=c("#000000", "#4CB944", "#00A7E1")) +
  scale_fill_manual(values=c("#000000", "#4CB944", "#00A7E1")) +
  ggtitle("Effect of Frequency of Observations on Heading Difference") +
  xlab("Frequency (%)") +
  ylab("Heading Difference (Degrees)") +
  theme_light()


ggplot(freq_predict_df, aes(x = Freq, y = pred_sync, color = interaction(Ablation,Darkness,sep=", "),
                       fill = interaction(Ablation,Darkness,sep=", "))) +
  geom_line() +
  facet_wrap(~ Flow) +
  guides(fill = "none", color = guide_legend(title = "Condition")) +
  scale_color_manual(values=c("#000000", "#4CB944", "#00A7E1")) +
  scale_fill_manual(values=c("#000000", "#4CB944", "#00A7E1")) +
  ggtitle("Effect of Frequency of Observations on Synchonization") +
  xlab("Frequency (%)") +
  ylab("Synchonization") +
  theme_light()

LS0tCnRpdGxlOiAiRmlzaCBDb21wYXJpc29ucyBTaW1wbGUgTW9kZWxzIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShjYXIpCmxpYnJhcnkodmlyaWRpcykKbGlicmFyeShib290KQpsaWJyYXJ5KG1nY3YpCmxpYnJhcnkoZm9yY2F0cykKbGlicmFyeShnZ3B1YnIpCmBgYAoKQWxyaWdodCwgc28gZnJvbSBhbGwgb2YgdGhpcyB3aGF0IGRvIEkga25vdz8KClNwZWVkIERpZmZlcmVuY2VzOgogIEZsb3cgaW5jcmVhc2VzIHNwZWVkIGRpZmZlcmVuY2VzCiAgQWJsYXRpb24gZGVjcmVhc2VzIHNwZWVkIGRpZmZlcmVuY2VzCiAgRGFya25lc3MgaW5jcmVhc2VzIHNwZWVkIGRpZmZlcmVuY2VzCiAgRGlzdGFuY2UgaW5jcmVhc2VzIHNwZWVkIGRpZmZlcmVuY2VzCiAgQW5nbGVzIGFyb3VuZCA5MCBkZWdyZWVzIGhhdmUgYSBiaWdnZXIgZGlmZmVyZW5jZSBpbiBzcGVlZAogIApIZWFkaW5nIERpZmZlcmVuY2VzOgogIEZpc2ggYXJlIG1vcmUgYWxpZ25lZCB3aGVuIHRoZXkgYXJlIGFyb3VuZCA5MCBkZWdyZWVzLCBzbGlnaHRseSBsZXNzIGluIGFibGF0ZWQgZmlzaAogIApTeW5jaHJvbml6YXRpb246CiAgRGFya25lc3MgaW5jcmVhc2VzIHN5bmNocm9uaXphdGlvbgogIApOTkQ6CiAgRGFya25lc3MgaW5jcmVhc2VzIE5ORAogIEZsb3cgZGVjcmVhc2VzIE5ORAogIApOZWFyZXN0IE5laWdoYm9yIEJlYXJpbmc6CiAgSW4gZGFya25lc3MgZmlzaCBhcmUgbW9yZSBpbiBmcm9udCBvciBiZWhpbmQKICBJbiBmbG93IGZpc2ggYXJlIG1vcmUgaW4gcG9zaXRpb25lZCBhbG9uZ3NpZGUgZWFjaCBvdGhlcgogIAogIAoKClNldHMgdXAgdGhlIGZ1bmN0aW9ucyB0aGF0IHdpbGwgYmUgdXNlZCBsYXRlciAKYGBge3J9CnJhZDJkZWcgPC0gZnVuY3Rpb24ocmFkKSB7KHJhZCAqIDE4MCkgLyAocGkpfQpkZWcycmFkIDwtIGZ1bmN0aW9uKGRlZykgeyhkZWcgKiBwaSkgLyAoMTgwKX0Kcm91bmRfYW55IDwtIGZ1bmN0aW9uKHgsIGFjY3VyYWN5LCBmPXJvdW5kKXtmKHgvIGFjY3VyYWN5KSAqIGFjY3VyYWN5fQphbmdfbWVhbiA8LSBmdW5jdGlvbih4KXtyYWQyZGVnKGF0YW4obWVhbihzaW4oZGVnMnJhZCh4KSkpL21lYW4oY29zKGRlZzJyYWQoeCkpKSkpfQoKZm9sZF9hbmdsZV8wXzM2MF90b18wXzE4MCA8LSBmdW5jdGlvbih4KXthYnMoYWJzKHgtMTgwKS0xODApfQoKZm9sZF9hbmdsZV9uZWdfMTgwXzE4MF90b19uZWdfOTBfOTAgPC0gZnVuY3Rpb24oeCl7aWZlbHNlKHggPiA5MCw5MC1hYnMoOTAteCksaWZlbHNlKHggPCAtOTAsIC05MCthYnMoLTkwLXgpLCB4KSl9CgptaW5fbiA8LSBmdW5jdGlvbih4LG4pe3NvcnQoeClbMTpuXX0KbWF4X24gPC0gZnVuY3Rpb24oeCxuKXtzb3J0KHgsZGVjcmVhc2luZyA9IFRSVUUpWzE6bl19CmBgYAoKUmVhZHMgaW4gdGhlIGRhdGEgYW5kIGFsdGVycyBpdCBhcyBuZWVkZWQgCmBgYHtyfQpjb21wX2RhdGEgPC0gcmVhZC5jc3YoIkZpc2hfQ29tcF9WYWx1ZXMuY3N2IikKY29tcF9kYXRhIDwtIG5hLm9taXQoY29tcF9kYXRhKQoKY29tcF9kYXRhIDwtIGNvbXBfZGF0YSAlPiUgbXV0YXRlKEZsb3cgPSBpZmVsc2UoRmxvdyA9PSAiMCIsICJGbG93IDAiLCAiRmxvdyAyIikpICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGUoQWJsYXRpb24gPSBpZmVsc2UoQWJsYXRpb24gPT0gIk4iLCAiTm8gQWJsYXRpb24iLCAiQWJsYXRlZCIpKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKERhcmtuZXNzID0gaWZlbHNlKERhcmtuZXNzID09ICJOIiwgIkxpZ2h0IiwgIkRhcmsiKSkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihEaXN0YW5jZSA8PSA0KSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyKGFicyhTcGVlZF9EaWZmKSA8PSA2KSAlPiUgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShTcGVlZF9EaWZmID0gYWJzKFNwZWVkX0RpZmYpKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKGZvbGRfaGVhZGluZ19kaWZmID0gYWJzKGZvbGRfYW5nbGVfbmVnXzE4MF8xODBfdG9fbmVnXzkwXzkwKEhlYWRpbmdfRGlmZikpKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKElzX0FsaWduZWQgPSBpZmVsc2UoSGVhZGluZ19EaWZmIDwgMzAsIDEsIDApKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKElzX1JldmVyc2VkID0gaWZlbHNlKEhlYWRpbmdfRGlmZiA+IDE1MCwgMSwgMCkpICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0ZShGaXNoLCBjKCJGaXNoMSIsICJGaXNoMiIpLHNlcD0ieCIpICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGUoRmxvdyA9IGZhY3RvcihGbG93KSwgQWJsYXRpb24gPSBmYWN0b3IoQWJsYXRpb24pLCBEYXJrbmVzcyA9IGZhY3RvcihEYXJrbmVzcykpICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGUoRmxvdyA9IGZjdF9yZWxldmVsKEZsb3csIGMoIkZsb3cgMCIsIkZsb3cgMiIpKSkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShBYmxhdGlvbiA9IGZjdF9yZWxldmVsKEFibGF0aW9uLCBjKCJObyBBYmxhdGlvbiIsIkFibGF0ZWQiKSkpICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGUoRGFya25lc3MgPSBmY3RfcmVsZXZlbChEYXJrbmVzcywgYygiTGlnaHQiLCJEYXJrIikpKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKHJhZF9BbmdsZSA9IEFuZ2xlKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKHNpbl9BbmdsZSA9IHNpbihyYWRfQW5nbGUpLCBjb3NfQW5nbGUgPSBjb3MocmFkX0FuZ2xlKSkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShGbG93X0FibGF0aW9uX0RhcmtuZXNzID0gZmFjdG9yKHBhc3RlKEZsb3csQWJsYXRpb24sRGFya25lc3Msc2VwPSIsICIpKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICNtdXRhdGUoQW5nbGUgPSBmb2xkX2FuZ2xlXzBfMzYwX3RvXzBfMTgwKEFuZ2xlKSkKCnN1bV9jb21wX2RhdGEgPC0gY29tcF9kYXRhICU+JSBtdXRhdGUoWF9EaXN0YW5jZSA9IHJvdW5kX2FueShYX0Rpc3RhbmNlLDAuMjUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBZX0Rpc3RhbmNlID0gcm91bmRfYW55KGFicyhZX0Rpc3RhbmNlKSwwLjI1KSkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cF9ieShGbG93LEFibGF0aW9uLERhcmtuZXNzLFhfRGlzdGFuY2UsWV9EaXN0YW5jZSkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdW1tYXJpc2UoU3BlZWRfRGlmZiA9IG1lYW4oU3BlZWRfRGlmZiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSGVhZGluZ19EaWZmID0gYW5nX21lYW4oSGVhZGluZ19EaWZmKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTeW5jID0gbWVhbihTeW5jKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGb2xkX0hlYWRpbmdfRGlmZiA9IG1lYW4oZm9sZF9oZWFkaW5nX2RpZmYpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIElzX0FsaWduZWQgPSBtZWFuKElzX0FsaWduZWQpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIElzX1JldmVyc2VkID0gbWVhbihJc19SZXZlcnNlZCkpCgpjb21wX2RhdGFfc3dpdGNoX2Zpc2ggPC0gY29tcF9kYXRhICU+JSBtdXRhdGUoRmlzaDMgPSBGaXNoMSkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShGaXNoMSA9IEZpc2gyKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKEZpc2gyID0gRmlzaDMpICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3QoLWMoRmlzaDMpKQoKY29tcF9kYXRhX05ORCA8LSBiaW5kX3Jvd3MoY29tcF9kYXRhLCBjb21wX2RhdGFfc3dpdGNoX2Zpc2gpICU+JSBncm91cF9ieShZZWFyLE1vbnRoLERheSxUcmlhbCxGaXNoMSxUYWlsYmVhdC5OdW0pICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihEaXN0YW5jZSA9PSBtaW4oRGlzdGFuY2UpKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmdyb3VwKCkKCmNvbXBfZGF0YV9uZWFyXzMgPC0gYmluZF9yb3dzKGNvbXBfZGF0YSwgY29tcF9kYXRhX3N3aXRjaF9maXNoKSAlPiUgZ3JvdXBfYnkoWWVhcixNb250aCxEYXksVHJpYWwsRmlzaDEsVGFpbGJlYXQuTnVtKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbGljZV9taW4oRGlzdGFuY2UsIG4gPSAzKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmdyb3VwKCkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzdGluY3QoRGlzdGFuY2UsIC5rZWVwX2FsbD0gVFJVRSkKYGBgCgojQmFzaWMgU3RhdHMKCmBgYHtyfQpzcGVlZF9hbm92YSA8LSBhb3YoU3BlZWRfRGlmZiB+IEZsb3cgKyBBYmxhdGlvbiArIERhcmtuZXNzICsgRmxvdzpBYmxhdGlvbiArIEZsb3c6RGFya25lc3MsIGRhdGEgPSBjb21wX2RhdGFfbmVhcl8zKQoKQW5vdmEoc3BlZWRfYW5vdmEpCgpoZWFkaW5nX2Fub3ZhIDwtIGFvdihmb2xkX2hlYWRpbmdfZGlmZiB+IEZsb3cgKyBBYmxhdGlvbiArIERhcmtuZXNzICsgRmxvdzpBYmxhdGlvbiArIEZsb3c6RGFya25lc3MsIGRhdGEgPSBjb21wX2RhdGFfbmVhcl8zKQoKQW5vdmEoaGVhZGluZ19hbm92YSkKCnN5bmNfYW5vdmEgPC0gYW92KFN5bmMgfiBGbG93ICsgQWJsYXRpb24gKyBEYXJrbmVzcyArIEZsb3c6QWJsYXRpb24gKyBGbG93OkRhcmtuZXNzLCBkYXRhID0gY29tcF9kYXRhX25lYXJfMykKCkFub3ZhKHN5bmNfYW5vdmEpCgpkaXN0X2Fub3ZhIDwtIGFvdihEaXN0YW5jZSB+IEZsb3cgKyBBYmxhdGlvbiArIERhcmtuZXNzICsgRmxvdzpBYmxhdGlvbiArIEZsb3c6RGFya25lc3MsIGRhdGEgPSBjb21wX2RhdGFfTk5EKQoKQW5vdmEoZGlzdF9hbm92YSkKCmFuZ2xlX2Fub3ZhIDwtIGFvdihBbmdsZSB+IEZsb3cgKyBBYmxhdGlvbiArIERhcmtuZXNzICsgRmxvdzpBYmxhdGlvbiArIEZsb3c6RGFya25lc3MsIGRhdGEgPSBjb21wX2RhdGFfTk5EKQoKQW5vdmEoZGlzdF9hbm92YSkKYGBgCgpgYGB7cn0KZ2dwbG90KGNvbXBfZGF0YV9uZWFyXzMsIGFlcyh4ID0gY29zKGRlZzJyYWQoQW5nbGUpKSkpKwogIGdlb21faGlzdG9ncmFtKCkrCiAgZmFjZXRfd3JhcCh+IEZsb3cgKyBBYmxhdGlvbiArIERhcmtuZXNzKQoKZ2dwbG90KGNvbXBfZGF0YV9uZWFyXzMsIGFlcyh4ID0gc2luKGRlZzJyYWQoQW5nbGUpKSkpKwogIGdlb21faGlzdG9ncmFtKCkrCiAgZmFjZXRfd3JhcCh+IEZsb3cgKyBBYmxhdGlvbiArIERhcmtuZXNzKQpgYGAKCgoKYGBge3J9CmdncGxvdChjb21wX2RhdGFfbmVhcl8zLCBhZXMoeCA9IEZsb3csIHkgPSBTcGVlZF9EaWZmLCBmaWxsID0gaW50ZXJhY3Rpb24oQWJsYXRpb24sRGFya25lc3Msc2VwPSIsICIpKSkrCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2hhcGUgPSBOQSkgKwogIGd1aWRlcyhmaWxsID0gZ3VpZGVfbGVnZW5kKHRpdGxlID0gIkNvbmRpdGlvbiIpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIiNFRUVFRUUiLCAiIzRDQjk0NCIsICIjMDBBN0UxIikpICsKICBnZ3RpdGxlKCJFZmZlY3Qgb2YgQXZhaWxhYmxlIFNlbnNlcyBvbiBTcGVlZCBEaWZmZXJlbmNlIikgKwogIHhsYWIoIiIpICsKICB5bGFiKCJTcGVlZCBEaWZmZXJlbmNlIChCTC9zKSIpICsKICB5bGltKC0wLjEsMi41KSArCiAgdGhlbWVfbGlnaHQoKQoKZ2dwbG90KGNvbXBfZGF0YV9uZWFyXzMsIGFlcyh4ID0gRmxvdywgeSA9IGZvbGRfaGVhZGluZ19kaWZmLCBmaWxsID0gaW50ZXJhY3Rpb24oQWJsYXRpb24sRGFya25lc3Msc2VwPSIsICIpKSkrCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2hhcGUgPSBOQSkgKwogIGd1aWRlcyhmaWxsID0gZ3VpZGVfbGVnZW5kKHRpdGxlID0gIkNvbmRpdGlvbiIpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIiNFRUVFRUUiLCAiIzRDQjk0NCIsICIjMDBBN0UxIikpICsKICBnZ3RpdGxlKCJFZmZlY3Qgb2YgQXZhaWxhYmxlIFNlbnNlcyBvbiBIZWFkaW5nIERpZmZlcmVuY2UiKSArCiAgeGxhYigiIikgKwogIHlsYWIoIkhlYWRpbmcgRGlmZmVyZW5jZSAoRGVncmVlcykiKSArCiAgdGhlbWVfbGlnaHQoKQoKZ2dwbG90KGNvbXBfZGF0YV9uZWFyXzMsIGFlcyh4ID0gRmxvdywgeSA9IFN5bmMsIGZpbGwgPSBpbnRlcmFjdGlvbihBYmxhdGlvbixEYXJrbmVzcyxzZXA9IiwgIikpKSsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BKSArCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQodGl0bGUgPSAiQ29uZGl0aW9uIikpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiI0VFRUVFRSIsICIjNENCOTQ0IiwgIiMwMEE3RTEiKSkgKwogIGdndGl0bGUoIkVmZmVjdCBvZiBBdmFpbGFibGUgU2Vuc2VzIG9uIFRhaWxiZWF0IFN5bmNob25pemF0aW9uIikgKwogIHhsYWIoIiIpICsKICB5bGFiKCJTeW5jcm9uaXphdGlvbiIpICsKICB0aGVtZV9saWdodCgpCgpnZ3Bsb3QoY29tcF9kYXRhX25lYXJfMywgYWVzKHggPSBGbG93LCB5ID0gRGlzdGFuY2UsIGZpbGwgPSBpbnRlcmFjdGlvbihBYmxhdGlvbixEYXJrbmVzcyxzZXA9IiwgIikpKSsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BKSArCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQodGl0bGUgPSAiQ29uZGl0aW9uIikpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiI0VFRUVFRSIsICIjNENCOTQ0IiwgIiMwMEE3RTEiKSkgKwogIGdndGl0bGUoIkVmZmVjdCBvZiBBdmFpbGFibGUgU2Vuc2VzIG9uIE5lYXJlc3QgTmVpZ2hib3IgRGlzdGFuY2UgKE5ORCkiKSArCiAgeGxhYigiIikgKwogIHlsYWIoIk5ORCAoQkwpIikgKwogIHRoZW1lX2xpZ2h0KCkKCmdncGxvdChjb21wX2RhdGFfbmVhcl8zLCBhZXMoeCA9IEZsb3csIHkgPSBBbmdsZSwgZmlsbCA9IGludGVyYWN0aW9uKEFibGF0aW9uLERhcmtuZXNzLHNlcD0iLCAiKSkpKwogIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlID0gTkEpICsKICBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZCh0aXRsZSA9ICJDb25kaXRpb24iKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCIjRUVFRUVFIiwgIiM0Q0I5NDQiLCAiIzAwQTdFMSIpKSArCiAgZ2d0aXRsZSgiRWZmZWN0IG9mIEF2YWlsYWJsZSBTZW5zZXMgb24gTmVhcmVzdCBOZWlnaGJvciBCZWFyaW5nIikgKwogIHhsYWIoIiIpICsKICB5bGFiKCJOZWFyZXN0IE5laWdoYm9yIEJlYXJpbmcgKERlZ3JlZXMpIikgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBjKDMwLDYwLDkwLDEyMCwxNTApKSArCiAgdGhlbWVfbGlnaHQoKQoKYGBgCgpUcnlpbmcgR0FNcwoKYGBge3J9CnNwZWVkX2dhbSA8LSBnYW0oU3BlZWRfRGlmZiB+IHMoRGlzdGFuY2UsQW5nbGUsYnk9Rmxvd19BYmxhdGlvbl9EYXJrbmVzcyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBjb21wX2RhdGFfbmVhcl8zKQoKc3VtbWFyeShzcGVlZF9nYW0pCgpoZWFkaW5nX2dhbSA8LSBnYW0oZm9sZF9oZWFkaW5nX2RpZmYgfiBzKERpc3RhbmNlLEFuZ2xlLGJ5PUZsb3dfQWJsYXRpb25fRGFya25lc3MpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gY29tcF9kYXRhX25lYXJfMykKCnN1bW1hcnkoaGVhZGluZ19nYW0pCgpzeW5jX2dhbSA8LSBnYW0oU3luYyB+IHMoRGlzdGFuY2UsQW5nbGUsYnk9Rmxvd19BYmxhdGlvbl9EYXJrbmVzcyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBjb21wX2RhdGFfbmVhcl8zKQoKc3VtbWFyeShzeW5jX2dhbSkKYGBgCgoKTm93IHdlIG1ha2Ugc29tZSBwcmVkaWN0aW9ucyBmb3IgdGhpcy4KYGBge3J9CmQgPC0gc2VxKGZyb20gPSAwLCB0byA9IDMsIGJ5ID0gMC4xKQphIDwtIHNlcShmcm9tID0gMCwgdG8gPSAxODAsIGJ5ID0gMTApCgpmbG93cyA8LSBjKCJGbG93IDAiLCAiRmxvdyAyIikKYWJsYXRpb24gPC0gYygiTm8gQWJsYXRpb24iLCAiQWJsYXRlZCIpCmRhcmsgPC0gYygiTGlnaHQiLCJEYXJrIikKCnByZWRpY3RfZGYgPC0gZXhwYW5kLmdyaWQoRGlzdGFuY2UgPSBkLCBBbmdsZSA9IGEsIEZsb3cgPSBmbG93cywgQWJsYXRpb24gPSBhYmxhdGlvbiwgRGFya25lc3MgPSBkYXJrKQoKcHJlZGljdF9kZiA8LSBwcmVkaWN0X2RmICU+JSBtdXRhdGUoRmxvd19BYmxhdGlvbl9EYXJrbmVzcyA9IGZhY3RvcihwYXN0ZShGbG93LEFibGF0aW9uLERhcmtuZXNzLHNlcD0iLCAiKSkpICU+JSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcighKEFibGF0aW9uID09ICJBYmxhdGVkIiAmIERhcmtuZXNzID09ICdEYXJrJykpCgpwcmVkaWN0X2RmIDwtIHByZWRpY3RfZGYgJT4lIG11dGF0ZShwcmVkX3NwZWVkX2RpZmYgPSBwcmVkaWN0LmdhbShzcGVlZF9nYW0scHJlZGljdF9kZiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZWRfaGVhZGluZ19kaWZmID0gcHJlZGljdC5nYW0oaGVhZGluZ19nYW0scHJlZGljdF9kZiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZWRfc3luYyA9IHByZWRpY3QuZ2FtKHN5bmNfZ2FtLHByZWRpY3RfZGYpKQoKcHJlZGljdF9kZiA8LSBwcmVkaWN0X2RmICU+JSBncm91cF9ieShEaXN0YW5jZSxGbG93LEFibGF0aW9uLERhcmtuZXNzKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGUobWVhbl9TcGVlZF9EaXN0YW5jZSA9IG1lYW4ocHJlZF9zcGVlZF9kaWZmKSwgc2RfU3BlZWRfRGlzdGFuY2UgPSBzZChwcmVkX3NwZWVkX2RpZmYpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWFuX0hlYWRpbmdfRGlzdGFuY2UgPSBtZWFuKHByZWRfaGVhZGluZ19kaWZmKSwgc2RfSGVhZGluZ19EaXN0YW5jZSA9IHNkKHByZWRfaGVhZGluZ19kaWZmKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVhbl9TeW5jX0Rpc3RhbmNlID0gbWVhbihwcmVkX3N5bmMpLCBzZF9TeW5jX0Rpc3RhbmNlID0gc2QocHJlZF9zeW5jKSkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5ncm91cCgpICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwX2J5KEFuZ2xlLEZsb3csQWJsYXRpb24sRGFya25lc3MpICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShtZWFuX1NwZWVkX0FuZ2xlID0gbWVhbihwcmVkX3NwZWVkX2RpZmYpLCBzZF9TcGVlZF9BbmdsZSA9IHNkKHByZWRfc3BlZWRfZGlmZiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW5fSGVhZGluZ19BbmdsZSA9IG1lYW4ocHJlZF9oZWFkaW5nX2RpZmYpLCBzZF9IZWFkaW5nX0FuZ2xlID0gc2QocHJlZF9oZWFkaW5nX2RpZmYpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWFuX1N5bmNfQW5nbGUgPSBtZWFuKHByZWRfc3luYyksIHNkX1N5bmNfQW5nbGUgPSBzZChwcmVkX3N5bmMpKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmdyb3VwKCkKYGBgCgpBbmQgbm93IHdlIGdyYXBoIHRob3NlPwoKYGBge3J9CmdncGxvdChwcmVkaWN0X2RmLCBhZXMoeCA9IERpc3RhbmNlLCB5ID0gbWVhbl9TcGVlZF9EaXN0YW5jZSwgY29sb3IgPSBpbnRlcmFjdGlvbihBYmxhdGlvbixEYXJrbmVzcyxzZXA9IiwgIiksCiAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IGludGVyYWN0aW9uKEFibGF0aW9uLERhcmtuZXNzLHNlcD0iICIpKSkgKwogIGdlb21fbGluZSgpICsKICAjZ2VvbV9wb2ludChkYXRhPXByZWRpY3RfZGYsIGFlcyh4ID0gRGlzdGFuY2UsIHkgPSBwcmVkX3NwZWVkX2RpZmYsIGFscGhhID0gMC4xNSkpICsKICBnZW9tX3JpYmJvbihhZXMoeW1pbiA9IG1lYW5fU3BlZWRfRGlzdGFuY2Utc2RfU3BlZWRfRGlzdGFuY2UsIHltYXggPSBtZWFuX1NwZWVkX0Rpc3RhbmNlK3NkX1NwZWVkX0Rpc3RhbmNlKSwKICAgICAgICAgICAgICBsaW5ldHlwZSA9IDAsCiAgICAgICAgICAgICAgYWxwaGEgPSAwLjEpICsKICBmYWNldF93cmFwKH4gRmxvdykgKwogIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBjb2xvciA9IGd1aWRlX2xlZ2VuZCh0aXRsZSA9ICJDb25kaXRpb24iKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiIzAwMDAwMCIsICIjNENCOTQ0IiwgIiMwMEE3RTEiKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCIjMDAwMDAwIiwgIiM0Q0I5NDQiLCAiIzAwQTdFMSIpKSArCiAgZ2d0aXRsZSgiRWZmZWN0IG9mIERpc3RhbmNlIGFuZCBTZW5zZXMgb24gU3BlZWQgRGlmZmVyZW5jZSIpICsKICB4bGFiKCJEaXN0YW5jZSAoQkwpIikgKwogIHlsYWIoIlNwZWVkIERpZmZlcmVuY2UgKEJML3MpIikgKwogIHlsaW0oMCwxLjUpICsKICB0aGVtZV9saWdodCgpCgpnZ3Bsb3QocHJlZGljdF9kZiwgYWVzKHggPSBEaXN0YW5jZSwgeSA9IG1lYW5fSGVhZGluZ19EaXN0YW5jZSwgY29sb3IgPSBpbnRlcmFjdGlvbihBYmxhdGlvbixEYXJrbmVzcyxzZXA9IiwgIiksCiAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IGludGVyYWN0aW9uKEFibGF0aW9uLERhcmtuZXNzLHNlcD0iLCAiKSkpICsKICBnZW9tX2xpbmUoKSArCiAgI2dlb21fcG9pbnQoZGF0YT1wcmVkaWN0X2RmLCBhZXMoeCA9IERpc3RhbmNlLCB5ID0gcHJlZF9oZWFkaW5nX2RpZmYsIGFscGhhID0gMC4xNSkpICsKICBnZW9tX3JpYmJvbihhZXMoeW1pbiA9IG1lYW5fSGVhZGluZ19EaXN0YW5jZS1zZF9IZWFkaW5nX0Rpc3RhbmNlLCB5bWF4ID0gbWVhbl9IZWFkaW5nX0Rpc3RhbmNlK3NkX0hlYWRpbmdfRGlzdGFuY2UpLAogICAgICAgICAgICAgIGxpbmV0eXBlID0gMCwKICAgICAgICAgICAgICBhbHBoYSA9IDAuMSkgKwogIGZhY2V0X3dyYXAofiBGbG93KSArCiAgZ3VpZGVzKGZpbGwgPSAibm9uZSIsIGNvbG9yID0gZ3VpZGVfbGVnZW5kKHRpdGxlID0gIkNvbmRpdGlvbiIpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCIjMDAwMDAwIiwgIiM0Q0I5NDQiLCAiIzAwQTdFMSIpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIiMwMDAwMDAiLCAiIzRDQjk0NCIsICIjMDBBN0UxIikpICsKICBnZ3RpdGxlKCJFZmZlY3Qgb2YgRGlzdGFuY2UgYW5kIFNlbnNlcyBvbiBIZWFkaW5nIERpZmZlcmVuY2UiKSArCiAgeGxhYigiRGlzdGFuY2UgKEJMKSIpICsKICB5bGFiKCJIZWFkaW5nIERpZmZlcmVuY2UgKERlZ3JlZXMpIikgKwogIHlsaW0oMCw1MCkgKwogIHRoZW1lX2xpZ2h0KCkKCmdncGxvdChwcmVkaWN0X2RmLCBhZXMoeCA9IERpc3RhbmNlLCB5ID0gbWVhbl9TeW5jX0Rpc3RhbmNlLCBjb2xvciA9IGludGVyYWN0aW9uKEFibGF0aW9uLERhcmtuZXNzLHNlcD0iLCAiKSwKICAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gaW50ZXJhY3Rpb24oQWJsYXRpb24sRGFya25lc3Msc2VwPSIsICIpKSkgKwogIGdlb21fbGluZSgpICsKICAjZ2VvbV9wb2ludChkYXRhPXByZWRpY3RfZGYsIGFlcyh4ID0gRGlzdGFuY2UsIHkgPSBwcmVkX3N5bmMsIGFscGhhID0gMC4xNSkpICsKICBnZW9tX3JpYmJvbihhZXMoeW1pbiA9IG1lYW5fU3luY19EaXN0YW5jZS1zZF9TeW5jX0Rpc3RhbmNlLCB5bWF4ID0gbWVhbl9TeW5jX0Rpc3RhbmNlK3NkX1N5bmNfRGlzdGFuY2UpLAogICAgICAgICAgICAgIGxpbmV0eXBlID0gMCwKICAgICAgICAgICAgICBhbHBoYSA9IDAuMSkgKwogIGZhY2V0X3dyYXAofiBGbG93KSArCiAgZ3VpZGVzKGZpbGwgPSAibm9uZSIsIGNvbG9yID0gZ3VpZGVfbGVnZW5kKHRpdGxlID0gIkNvbmRpdGlvbiIpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCIjMDAwMDAwIiwgIiM0Q0I5NDQiLCAiIzAwQTdFMSIpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIiMwMDAwMDAiLCAiIzRDQjk0NCIsICIjMDBBN0UxIikpICsKICBnZ3RpdGxlKCJFZmZlY3Qgb2YgRGlzdGFuY2UgYW5kIFNlbnNlcyBvbiBTeW5jaG9uaXphdGlvbiIpICsKICB4bGFiKCJEaXN0YW5jZSAoQkwpIikgKwogIHlsYWIoIlN5bmNob25pemF0aW9uIikgKwogIHlsaW0oMCwxKSsKICB0aGVtZV9saWdodCgpCmBgYApgYGB7cn0KZ2dwbG90KHByZWRpY3RfZGYsIGFlcyh4ID0gQW5nbGUsIHkgPSBtZWFuX1NwZWVkX0FuZ2xlLCBjb2xvciA9IGludGVyYWN0aW9uKEFibGF0aW9uLERhcmtuZXNzLHNlcD0iLCAiKSwKICAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gaW50ZXJhY3Rpb24oQWJsYXRpb24sRGFya25lc3Msc2VwPSIsICIpKSkgKwogIGdlb21fbGluZSgpICsKICAjZ2VvbV9wb2ludChkYXRhPXByZWRpY3RfZGYsIGFlcyh4ID0gQW5nbGUsIHkgPSBwcmVkX3NwZWVkX2RpZmYsIGFscGhhID0gMC4xNSkpICsKICBnZW9tX3JpYmJvbihhZXMoeW1pbiA9IG1lYW5fU3BlZWRfQW5nbGUtc2RfU3BlZWRfQW5nbGUsIHltYXggPSBtZWFuX1NwZWVkX0FuZ2xlK3NkX1NwZWVkX0FuZ2xlKSwKICAgICAgICAgICAgICBsaW5ldHlwZSA9IDAsCiAgICAgICAgICAgICAgYWxwaGEgPSAwLjEpICsKICBmYWNldF93cmFwKH4gRmxvdykgKwogIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBjb2xvciA9IGd1aWRlX2xlZ2VuZCh0aXRsZSA9ICJDb25kaXRpb24iKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiIzAwMDAwMCIsICIjNENCOTQ0IiwgIiMwMEE3RTEiKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCIjMDAwMDAwIiwgIiM0Q0I5NDQiLCAiIzAwQTdFMSIpKSArCiAgZ2d0aXRsZSgiRWZmZWN0IG9mIEJlYXJpbmcgYW5kIFNlbnNlcyBvbiBTcGVlZCBEaWZmZXJlbmNlIikgKwogIHhsYWIoIkJlYXJpbmcgKERlZ3JlZXMpIikgKwogIHlsYWIoIlNwZWVkIERpZmZlcmVuY2UgKEJML3MpIikgKwogIHlsaW0oMCwxLjUpICsKICB0aGVtZV9saWdodCgpCgpnZ3Bsb3QocHJlZGljdF9kZiwgYWVzKHggPSBBbmdsZSwgeSA9IG1lYW5fSGVhZGluZ19BbmdsZSwgY29sb3IgPSBpbnRlcmFjdGlvbihBYmxhdGlvbixEYXJrbmVzcyxzZXA9IiwgIiksCiAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IGludGVyYWN0aW9uKEFibGF0aW9uLERhcmtuZXNzLHNlcD0iLCAiKSkpICsKICBnZW9tX2xpbmUoKSArCiAgI2dlb21fcG9pbnQoZGF0YT1wcmVkaWN0X2RmLCBhZXMoeCA9IEFuZ2xlLCB5ID0gcHJlZF9oZWFkaW5nX2RpZmYsIGFscGhhID0gMC4xNSkpICsKICBnZW9tX3JpYmJvbihhZXMoeW1pbiA9IG1lYW5fSGVhZGluZ19BbmdsZS1zZF9IZWFkaW5nX0FuZ2xlLCB5bWF4ID0gbWVhbl9IZWFkaW5nX0FuZ2xlK3NkX0hlYWRpbmdfQW5nbGUpLAogICAgICAgICAgICAgIGxpbmV0eXBlID0gMCwKICAgICAgICAgICAgICBhbHBoYSA9IDAuMSkgKwogIGZhY2V0X3dyYXAofiBGbG93KSArCiAgZ3VpZGVzKGZpbGwgPSAibm9uZSIsIGNvbG9yID0gZ3VpZGVfbGVnZW5kKHRpdGxlID0gIkNvbmRpdGlvbiIpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCIjMDAwMDAwIiwgIiM0Q0I5NDQiLCAiIzAwQTdFMSIpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIiMwMDAwMDAiLCAiIzRDQjk0NCIsICIjMDBBN0UxIikpICsKICBnZ3RpdGxlKCJFZmZlY3Qgb2YgQmVhcmluZyBhbmQgU2Vuc2VzIG9uIEhlYWRpbmcgRGlmZmVyZW5jZSIpICsKICB4bGFiKCJBbmdsZSAoRGVncmVlcykiKSArCiAgeWxhYigiSGVhZGluZyBEaWZmZXJlbmNlIChEZWdyZWVzKSIpICsKICB5bGltKDAsNTApICsKICB0aGVtZV9saWdodCgpCgpnZ3Bsb3QocHJlZGljdF9kZiwgYWVzKHggPSBBbmdsZSwgeSA9IG1lYW5fU3luY19BbmdsZSwgY29sb3IgPSBpbnRlcmFjdGlvbihBYmxhdGlvbixEYXJrbmVzcyxzZXA9IiwgIiksCiAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IGludGVyYWN0aW9uKEFibGF0aW9uLERhcmtuZXNzLHNlcD0iLCAiKSkpICsKICBnZW9tX2xpbmUoKSArCiAjZ2VvbV9wb2ludChkYXRhPXByZWRpY3RfZGYsIGFlcyh4ID0gQW5nbGUsIHkgPSBwcmVkX3N5bmMsIGFscGhhID0gMC4xNSkpICsKICBnZW9tX3JpYmJvbihhZXMoeW1pbiA9IG1lYW5fU3luY19BbmdsZS1zZF9TeW5jX0FuZ2xlLCB5bWF4ID0gbWVhbl9TeW5jX0FuZ2xlK3NkX1N5bmNfQW5nbGUpLAogICAgICAgICAgICAgIGxpbmV0eXBlID0gMCwKICAgICAgICAgICAgICBhbHBoYSA9IDAuMSkgKwogIGZhY2V0X3dyYXAofiBGbG93KSArCiAgZ3VpZGVzKGZpbGwgPSAibm9uZSIsIGNvbG9yID0gZ3VpZGVfbGVnZW5kKHRpdGxlID0gIkNvbmRpdGlvbiIpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCIjMDAwMDAwIiwgIiM0Q0I5NDQiLCAiIzAwQTdFMSIpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIiMwMDAwMDAiLCAiIzRDQjk0NCIsICIjMDBBN0UxIikpICsKICBnZ3RpdGxlKCJFZmZlY3Qgb2YgQmVhcmluZyBhbmQgU2Vuc2VzIG9uIFN5bmNob25pemF0aW9uIikgKwogIHhsYWIoIkJlYXJpbmcgKERlZ3JlZXMpIikgKwogIHlsYWIoIlN5bmNob25pemF0aW9uIikgKwogIHlsaW0oMCwxKSsKICB0aGVtZV9saWdodCgpCmBgYApEZW5zaXR5IHZzIFRoaW5ncwoKCgpgYGB7cn0KZGlzdF9iaW5fc2l6ZSA8LSAxCmFuZ2xlX2Jpbl9zaXplIDwtIDMwCgpjb21wX2RhdGFfZnJlcXMgPC0gY29tcF9kYXRhX25lYXJfMyAlPiUgbXV0YXRlKERpc3RfYmluID0gcm91bmRfYW55KERpc3RhbmNlLCBkaXN0X2Jpbl9zaXplKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQW5nbGVfYmluID0gcm91bmRfYW55KEFuZ2xlLCBhbmdsZV9iaW5fc2l6ZSkpICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXBfYnkoRmxvdyxEYXJrbmVzcyxBYmxhdGlvbiwgRGlzdF9iaW4sIEFuZ2xlX2JpbixGbG93X0FibGF0aW9uX0RhcmtuZXNzKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShDb3VudCA9IG4oKSkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmdyb3VwKCkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cF9ieShGbG93LERhcmtuZXNzLEFibGF0aW9uLEZsb3dfQWJsYXRpb25fRGFya25lc3MpICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKEZyZXEgPSBDb3VudC9uKCkpICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5ncm91cCgpICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXBfYnkoRmxvdyxEYXJrbmVzcyxBYmxhdGlvbixEaXN0X2JpbixBbmdsZV9iaW4sRmxvd19BYmxhdGlvbl9EYXJrbmVzcykgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdW1tYXJpc2UoU3BlZWRfRGlmZiA9IG1lYW4oU3BlZWRfRGlmZiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRm9sZF9IZWFkaW5nX0RpZmYgPSBhbmdfbWVhbihmb2xkX2hlYWRpbmdfZGlmZiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU3luYyA9IG1lYW4oU3luYyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRnJlcSA9IG1lYW4oRnJlcSkpCgpgYGAKCmBgYHtyfQpmcmVxX3NwZWVkX2dsbSA8LSBnbG0oU3BlZWRfRGlmZiB+IEZyZXEqKEZsb3crRGFya25lc3MrQWJsYXRpb24rRmxvdzpBYmxhdGlvbitGbG93OkRhcmtuZXNzKSwgZGF0YSA9IGNvbXBfZGF0YV9mcmVxcykKCnN1bW1hcnkoZnJlcV9zcGVlZF9nbG0pCgpmcmVxX2hlYWRpbmdfZ2xtIDwtIGdsbShGb2xkX0hlYWRpbmdfRGlmZiB+IEZyZXEqKEZsb3crRGFya25lc3MrQWJsYXRpb24rRmxvdzpBYmxhdGlvbitGbG93OkRhcmtuZXNzKSwgZGF0YSA9IGNvbXBfZGF0YV9mcmVxcykKCnN1bW1hcnkoZnJlcV9oZWFkaW5nX2dsbSkKCmZyZXFfc3luY19nbG0gPC0gZ2xtKFN5bmMgfiBGcmVxKihGbG93K0RhcmtuZXNzK0FibGF0aW9uK0Zsb3c6QWJsYXRpb24rRmxvdzpEYXJrbmVzcyksIGRhdGEgPSBjb21wX2RhdGFfZnJlcXMpCgpzdW1tYXJ5KGZyZXFfc3luY19nbG0pCgpmcmVxX3NwZWVkX2dhbSA8LSBnYW0oU3BlZWRfRGlmZiB+IHMoRnJlcSxieT1GbG93X0FibGF0aW9uX0RhcmtuZXNzKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGNvbXBfZGF0YV9mcmVxcykKCnN1bW1hcnkoZnJlcV9zcGVlZF9nYW0pCgpmcmVxX2hlYWRpbmdfZ2FtIDwtIGdhbShGb2xkX0hlYWRpbmdfRGlmZiB+IHMoRnJlcSxieT1GbG93X0FibGF0aW9uX0RhcmtuZXNzKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGNvbXBfZGF0YV9mcmVxcykKCnN1bW1hcnkoZnJlcV9oZWFkaW5nX2dhbSkKCmZyZXFfc3luY19nYW0gPC0gZ2FtKFN5bmMgfiBzKEZyZXEsYnk9Rmxvd19BYmxhdGlvbl9EYXJrbmVzcyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBjb21wX2RhdGFfZnJlcXMpCgpzdW1tYXJ5KGZyZXFfc3luY19nYW0pCmBgYAoKTm93IHdlIG1ha2Ugc29tZSBwcmVkaWN0aW9ucyBmb3IgdGhpcy4KYGBge3J9CmYgPC0gc2VxKGZyb20gPSAwLjAwNSwgdG8gPSAwLjA3LCBieSA9IDAuMDAxKQoKZmxvd3MgPC0gYygiRmxvdyAwIiwgIkZsb3cgMiIpCmFibGF0aW9uIDwtIGMoIk5vIEFibGF0aW9uIiwgIkFibGF0ZWQiKQpkYXJrIDwtIGMoIkxpZ2h0IiwiRGFyayIpCgpmcmVxX3ByZWRpY3RfZGYgPC0gZXhwYW5kLmdyaWQoRnJlcSA9IGYsIEZsb3cgPSBmbG93cywgQWJsYXRpb24gPSBhYmxhdGlvbiwgRGFya25lc3MgPSBkYXJrKQoKZnJlcV9wcmVkaWN0X2RmIDwtIGZyZXFfcHJlZGljdF9kZiAlPiUgbXV0YXRlKEZsb3dfQWJsYXRpb25fRGFya25lc3MgPSBmYWN0b3IocGFzdGUoRmxvdyxBYmxhdGlvbixEYXJrbmVzcyxzZXA9IiwgIikpKSAlPiUgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXIoIShBYmxhdGlvbiA9PSAiQWJsYXRlZCIgJiBEYXJrbmVzcyA9PSAnRGFyaycpKQoKZnJlcV9wcmVkaWN0X2RmIDwtIGZyZXFfcHJlZGljdF9kZiAlPiUgbXV0YXRlKHByZWRfc3BlZWRfZGlmZiA9IHByZWRpY3QuZ2FtKGZyZXFfc3BlZWRfZ2FtLGZyZXFfcHJlZGljdF9kZiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZWRfaGVhZGluZ19kaWZmID0gcHJlZGljdC5nYW0oZnJlcV9oZWFkaW5nX2dhbSxmcmVxX3ByZWRpY3RfZGYpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVkX3N5bmMgPSBwcmVkaWN0LmdhbShmcmVxX3N5bmNfZ2FtLGZyZXFfcHJlZGljdF9kZikpCgpgYGAKCgpgYGB7cn0KZ2dwbG90KGNvbXBfZGF0YV9mcmVxcywgYWVzKHggPSBGcmVxLCB5ID0gU3BlZWRfRGlmZiwgY29sb3IgPSBpbnRlcmFjdGlvbihBYmxhdGlvbixEYXJrbmVzcyxzZXA9IiwgIiksCiAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IGludGVyYWN0aW9uKEFibGF0aW9uLERhcmtuZXNzLHNlcD0iLCAiKSkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC41KSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgZm9ybXVsYSA9ICJ5IH4geCIsIHNlID0gRkFMU0UpICsKICBmYWNldF93cmFwKH4gRmxvdykgKwogIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBjb2xvciA9IGd1aWRlX2xlZ2VuZCh0aXRsZSA9ICJDb25kaXRpb24iKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiIzAwMDAwMCIsICIjNENCOTQ0IiwgIiMwMEE3RTEiKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCIjMDAwMDAwIiwgIiM0Q0I5NDQiLCAiIzAwQTdFMSIpKSArCiAgZ2d0aXRsZSgiRWZmZWN0IG9mIFByZWZlcmVuY2UgYW5kIFNlbnNlcyBvbiBTcGVlZCBEaWZmZXJlbmNlIikgKwogIHhsYWIoIkZyZXF1ZW5jeSBvZiBPYnNlcnZhdGlvbnMiKSArCiAgeWxhYigiU3BlZWQgRGlmZmVyZW5jZSAoQkwvcykiKSArCiAgdGhlbWVfbGlnaHQoKQoKZ2dwbG90KGNvbXBfZGF0YV9mcmVxcywgYWVzKHggPSBGcmVxLCB5ID0gRm9sZF9IZWFkaW5nX0RpZmYsIGNvbG9yID0gaW50ZXJhY3Rpb24oQWJsYXRpb24sRGFya25lc3Msc2VwPSIsICIpLAogICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBpbnRlcmFjdGlvbihBYmxhdGlvbixEYXJrbmVzcyxzZXA9IiwgIikpKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGZvcm11bGEgPSAieSB+IHgiLCBzZSA9IEZBTFNFKSArCiAgZmFjZXRfd3JhcCh+IEZsb3cpICsKICBndWlkZXMoZmlsbCA9ICJub25lIiwgY29sb3IgPSBndWlkZV9sZWdlbmQodGl0bGUgPSAiQ29uZGl0aW9uIikpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoIiMwMDAwMDAiLCAiIzRDQjk0NCIsICIjMDBBN0UxIikpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiIzAwMDAwMCIsICIjNENCOTQ0IiwgIiMwMEE3RTEiKSkgKwogIGdndGl0bGUoIkVmZmVjdCBvZiBQcmVmZXJlbmNlIGFuZCBTZW5zZXMgb24gSGVhZGluZyBEaWZmZXJlbmNlIikgKwogIHhsYWIoIkZyZXF1ZW5jeSBvZiBPYnNlcnZhdGlvbnMiKSArCiAgeWxhYigiSGVhZGluZyBEaWZmZXJlbmNlIChEZWdyZWVzKSIpICsKICB0aGVtZV9saWdodCgpCgpnZ3Bsb3QoY29tcF9kYXRhX2ZyZXFzLCBhZXMoeCA9IEZyZXEsIHkgPSBTeW5jLCBjb2xvciA9IGludGVyYWN0aW9uKEFibGF0aW9uLERhcmtuZXNzLHNlcD0iLCAiKSwKICAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gaW50ZXJhY3Rpb24oQWJsYXRpb24sRGFya25lc3Msc2VwPSIsICIpKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjUpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBmb3JtdWxhID0gInkgfiB4Iiwgc2UgPSBGQUxTRSkgKwogIGZhY2V0X3dyYXAofiBGbG93KSArCiAgZ3VpZGVzKGZpbGwgPSAibm9uZSIsIGNvbG9yID0gZ3VpZGVfbGVnZW5kKHRpdGxlID0gIkNvbmRpdGlvbiIpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCIjMDAwMDAwIiwgIiM0Q0I5NDQiLCAiIzAwQTdFMSIpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIiMwMDAwMDAiLCAiIzRDQjk0NCIsICIjMDBBN0UxIikpICsKICBnZ3RpdGxlKCJFZmZlY3Qgb2YgUHJlZmVyZW5jZSBhbmQgU2Vuc2VzIG9uIFN5bmNob25pemF0aW9uIikgKwogIHhsYWIoIkZyZXF1ZW5jeSBvZiBPYnNlcnZhdGlvbnMiKSArCiAgeWxhYigiU3luY2hvbml6YXRpb24iKSArCiAgdGhlbWVfbGlnaHQoKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoZnJlcV9wcmVkaWN0X2RmLCBhZXMoeCA9IEZyZXEsIHkgPSBwcmVkX3NwZWVkX2RpZmYsIGNvbG9yID0gaW50ZXJhY3Rpb24oQWJsYXRpb24sRGFya25lc3Msc2VwPSIsICIpLAogICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBpbnRlcmFjdGlvbihBYmxhdGlvbixEYXJrbmVzcyxzZXA9IiwgIikpKSArCiAgZ2VvbV9saW5lKCkgKwogIGZhY2V0X3dyYXAofiBGbG93KSArCiAgZ3VpZGVzKGZpbGwgPSAibm9uZSIsIGNvbG9yID0gZ3VpZGVfbGVnZW5kKHRpdGxlID0gIkNvbmRpdGlvbiIpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCIjMDAwMDAwIiwgIiM0Q0I5NDQiLCAiIzAwQTdFMSIpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIiMwMDAwMDAiLCAiIzRDQjk0NCIsICIjMDBBN0UxIikpICsKICBnZ3RpdGxlKCJFZmZlY3Qgb2YgRnJlcXVlbmN5IG9mIE9ic2VydmF0aW9ucyBvbiBTcGVlZCBEaWZmZXJlbmNlIikgKwogIHhsYWIoIkZyZXF1ZW5jeSAoJSkiKSArCiAgeWxhYigiU3BlZWQgRGlmZmVyZW5jZSAoQkwvcykiKSArCiAgdGhlbWVfbGlnaHQoKQoKZ2dwbG90KGZyZXFfcHJlZGljdF9kZiwgYWVzKHggPSBGcmVxLCB5ID0gcHJlZF9oZWFkaW5nX2RpZmYsIGNvbG9yID0gaW50ZXJhY3Rpb24oQWJsYXRpb24sRGFya25lc3Msc2VwPSIsICIpLAogICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBpbnRlcmFjdGlvbihBYmxhdGlvbixEYXJrbmVzcyxzZXA9IiwgIikpKSArCiAgZ2VvbV9saW5lKCkgKwogIGZhY2V0X3dyYXAofiBGbG93KSArCiAgZ3VpZGVzKGZpbGwgPSAibm9uZSIsIGNvbG9yID0gZ3VpZGVfbGVnZW5kKHRpdGxlID0gIkNvbmRpdGlvbiIpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCIjMDAwMDAwIiwgIiM0Q0I5NDQiLCAiIzAwQTdFMSIpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIiMwMDAwMDAiLCAiIzRDQjk0NCIsICIjMDBBN0UxIikpICsKICBnZ3RpdGxlKCJFZmZlY3Qgb2YgRnJlcXVlbmN5IG9mIE9ic2VydmF0aW9ucyBvbiBIZWFkaW5nIERpZmZlcmVuY2UiKSArCiAgeGxhYigiRnJlcXVlbmN5ICglKSIpICsKICB5bGFiKCJIZWFkaW5nIERpZmZlcmVuY2UgKERlZ3JlZXMpIikgKwogIHRoZW1lX2xpZ2h0KCkKCmdncGxvdChmcmVxX3ByZWRpY3RfZGYsIGFlcyh4ID0gRnJlcSwgeSA9IHByZWRfc3luYywgY29sb3IgPSBpbnRlcmFjdGlvbihBYmxhdGlvbixEYXJrbmVzcyxzZXA9IiwgIiksCiAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IGludGVyYWN0aW9uKEFibGF0aW9uLERhcmtuZXNzLHNlcD0iLCAiKSkpICsKICBnZW9tX2xpbmUoKSArCiAgZmFjZXRfd3JhcCh+IEZsb3cpICsKICBndWlkZXMoZmlsbCA9ICJub25lIiwgY29sb3IgPSBndWlkZV9sZWdlbmQodGl0bGUgPSAiQ29uZGl0aW9uIikpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoIiMwMDAwMDAiLCAiIzRDQjk0NCIsICIjMDBBN0UxIikpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiIzAwMDAwMCIsICIjNENCOTQ0IiwgIiMwMEE3RTEiKSkgKwogIGdndGl0bGUoIkVmZmVjdCBvZiBGcmVxdWVuY3kgb2YgT2JzZXJ2YXRpb25zIG9uIFN5bmNob25pemF0aW9uIikgKwogIHhsYWIoIkZyZXF1ZW5jeSAoJSkiKSArCiAgeWxhYigiU3luY2hvbml6YXRpb24iKSArCiAgdGhlbWVfbGlnaHQoKQpgYGAKCgo=